package com.maozzi.common.util;

import lombok.extern.slf4j.Slf4j;
import org.springframework.util.StringUtils;

import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.spec.SecretKeySpec;
import java.nio.charset.StandardCharsets;
import java.util.Base64;

/**
 * AES 加密工具类
 *
 * @author maozi
 */
@Slf4j
public class AesUtil {
    /**
     * 加密方式
     */
    private static final String AES = "AES";

    /**
     * 密钥长度
     */
    private static final Integer SECRET_KEY_LENGTH = 16;

    /**
     * 加密key
     */
    private static final String DEFAULT_SECRET_KEY = "demo";

    /**
     * 加密算法参数 算法名称/加密模式/数据填充方式
     */
    private static final String ALGORITHM = "AES/ECB/PKCS5Padding";

    private static Cipher cipher;

    static {
        try {
            KeyGenerator generator = KeyGenerator.getInstance(AES);
            generator.init(128);
            cipher = Cipher.getInstance(ALGORITHM);
        } catch (Exception e) {
            log.error("AES 工具类初始化错误", e);
        }

    }

    /**
     * 检查密钥长度，保持8长度
     *
     * @param secretKey 密钥
     * @return 返回
     */
    private static String checkSecretKey(String secretKey) {
        if (!StringUtils.hasText(secretKey)) {
            throw new RuntimeException("密钥不能为空");
        }

        if (secretKey.length() < SECRET_KEY_LENGTH) {
            int sub = SECRET_KEY_LENGTH - secretKey.length();
            return secretKey + String.format("%0" + sub + "d", 0);
        } else {
            return secretKey.substring(0, SECRET_KEY_LENGTH);
        }
    }

    /**
     * 加密
     *
     * @param content 需要加密的内容
     * @return 返回
     */
    public static String encrypt(String content) {
        return AesUtil.encrypt(content, "");
    }

    /**
     * 加密
     *
     * @param content   加密的字符串
     * @param secretKey key值
     * @return 返回加密
     */
    public static String encrypt(String content, String secretKey) {
        if (!StringUtils.hasText(content)) {
            log.error("{} 加密失败，内容为空", AES);

            return null;
        }

        secretKey = checkSecretKey(DEFAULT_SECRET_KEY + secretKey);
        try {
            cipher.init(Cipher.ENCRYPT_MODE, new SecretKeySpec(secretKey.getBytes(), AES));

            byte[] bytes = content.getBytes(StandardCharsets.UTF_8);
            byte[] b = cipher.doFinal(bytes);

            // base64算法进行转码,避免出现中文乱码
            return Base64.getMimeEncoder().encodeToString(b);
        } catch (Exception e) {
            log.error("{} 加密失败，内容：{}，密钥：{}，错误信息：", AES, content, secretKey, e);

            return null;
        }
    }

    /**
     * 解密
     *
     * @param content 需要解密的内容
     * @return 返回
     */
    public static String decrypt(String content) {
        return decrypt(content, "");
    }

    /**
     * 解密
     *
     * @param content   解密的字符串
     * @param secretKey 解密的key值
     * @return 返回解密
     */
    public static String decrypt(String content, String secretKey) {
        secretKey = checkSecretKey(DEFAULT_SECRET_KEY + secretKey);
        try {
            cipher.init(Cipher.DECRYPT_MODE, new SecretKeySpec(secretKey.getBytes(), AES));

            // base64算法进行转码,避免出现中文乱码
            byte[] bytes = content.getBytes(StandardCharsets.UTF_8);
            byte[] decode = Base64.getMimeDecoder().decode(bytes);
            byte[] decryptBytes = cipher.doFinal(decode);

            return new String(decryptBytes, StandardCharsets.UTF_8);
        } catch (Exception e) {
            log.error("{} 解密失败，内容：{}，密钥：{}，错误信息：", AES, content, secretKey, e);

            return null;
        }
    }

}